import { useRef } from "react";
import { useEffect } from "react";
import "./Canvas.css";






function Canvas() {
  let reqId = null
  const canvas = useRef(null);

  useEffect( () => {

    
    let ctx;
    let circleArr = [];
    let duration = 0;
    let playing = false;
    let btn1 = document.getElementById("btn1");
    let btn2 = document.getElementById("btn2");
    let btn3 = document.getElementById("btn3");
    let audio = document.getElementById("audio");
    let total = document.getElementById("total");

    /**
     * @desc  表盘特效
     * @param {*} rotate 起始角度deg
     * @param {*} scalenum 起始缩放大小scale
     * @returns
     */
    class CirLine {
      static instance;
      abs = 1; // 取值 +1 / -1  放大或缩小
      constructor(rotate, scalenum) {
        if (!CirLine.instance) {
          this.rotate = rotate;
          this.scalenum = scalenum;
          CirLine.instance = this;
        }
        return CirLine.instance;
      }
      move(array) {
        this.rotate += 0.1;
        this.scalenum -= (this.abs * (this.scalenum - 1)) / 200;
        drawCirLine(this.rotate, this.scalenum,array);
      }
    }
    // 音频频谱
    class GetAudio {
      audio;
      context;
      source;
      analyser;
      static instance;
      constructor() {
        if (!GetAudio.instance) {
          console.log('getaudio');
          this.context = new AudioContext();
          this.source = this.context.createMediaElementSource(audio); // 创建sourceNode关联audio元素
          this.analyser = this.context.createAnalyser(); // 创建音频分析器
          this.array = new Uint8Array(1024);
          this.init();
          GetAudio.instance = this;
        }
        return GetAudio.instance;
      }
      init() {
        this.source.connect(this.analyser);
        this.analyser.connect(this.context.destination);
        // this.analyser.fftSize = 512;
      }
      createAudio() {
        this.analyser.getByteFrequencyData(this.array);  // 获取频域的数据 拷贝到array
        // 音频频谱数组  分成1000份
        this.step = Math.round(this.array.length / 1000);
        ctx.save();
        var gradient = ctx.createLinearGradient(0, 0, 0, 389);
        gradient.addColorStop(1, "#0f00f0");
        gradient.addColorStop(0.8, "#ff0ff0");
        gradient.addColorStop(0.5, "#f00f00");
        ctx.fillStyle = gradient; //填充
        for (var i = 0; i < 1000; i++) {
          var value = this.array[i * this.step];
          ctx.fillRect(i * 15, 389, 10, -value * 1); //绘制上
          ctx.fillRect(i * 15, 389, 10, value * .5); //绘制下
          ctx.fillText('哈哈哈',0, 389)
        }
        ctx.restore();
        return this.array;
      }
    }

    loadinit();

    function loadinit() {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      btn1.onclick = () => changeBackgroundColor("red");
      btn2.onclick = () => changeBackgroundColor("blue");
      btn3.onclick = () => changeBackgroundColor("green");
      let timeId = null;

      btn1.onmouseenter = btn2.onmouseenter = btn3.onmouseenter =(e) => {
        timeId = setInterval(() => {
          createParticle(e);
        }, 10);
      };

      btn1.onmouseleave =btn2.onmouseleave = btn3.onmouseleave =() => {
        clearInterval(timeId);
      };

      audio.oncanplay = () => {
          console.log('加载完成',audio.duration);
          duration = audio.duration
      }
      audio.oncanplaythrough = () => {
      }

      audio.ontimeupdate = deb(function(){
          !playing && (playing = true)
          document.documentElement.style.setProperty('--w',audio.currentTime/duration*100 + '%')
          console.log();
          total.setAttribute('data-value',getAudioTime(audio.currentTime) + " / " + getAudioTime(duration))
      },800)

      audio.onpause = () => {
          playing = false
      }
      ctx = initCanvas();
      ctx.mstars = [];
      ctx.cirlines = [];
      createCirlce();
      new CirLine(0, 4);
      document.onmousemove = deb(moseMove, 10);
      document.body.onclick = () => {
        new GetAudio()
      }
      animation();
    }

    function getAudioTime(time) {
      let mini = parseInt(time / 60)
        .toString()
        .padStart(2, "0");
      let sec = parseInt(time % 60)
        .toString()
        .padStart(2, "0");
      return mini + " : " + sec;
    }

    function changeBackgroundColor(classname) {
      // new CirLine().abs *= -1;
      document.body.className = classname;
      if (!playing) {
        audio.play();
        playing = true
      } else {
        audio.pause();
        playing = false
      }
    }

    function moseMove(e) {
      let X = (e.clientX / window.innerWidth).toFixed(2);
      document.body.style.setProperty("--deg", `${360 * X}deg`);
      if (ctx) {
        createParticle(e);
      }
    }

    // 节流函数
    function deb(fn, delay) {
      let timeId;
      return function () {
        let args = arguments;
        let context = this;
        if (!timeId) {
          timeId = setTimeout(function () {
            timeId = null;
            fn.apply(context, args);
          }, delay);
        }
      };
    }

    function initCanvas() {
      const ctx = canvas.getContext("2d");
      ctx.beginPath();
      ctx.strokeStyle = "#fff";
      ctx.paths = [];
      return ctx;
    }
    // 基类
    class Arc {
      constructor(ctx, x, y, size, color) {
        this.x = x;
        this.y = y;
        this.size = size;
        this.color = color;
        this.ctx = ctx;
        this.rotate = 0;
        this.init();
      }
      init() {
        drawHeart(this.ctx, this.x, this.y, this.size, this.rotate, this.color);
      }
      destory() {}
    }

    class Star extends Arc {
      /**
       * @desc 流星
       * @param {*} ctx canvas上下文
       * @param {*} x x坐标位置
       * @param {*} y y坐标位置
       * @param {*} size 大小
       * @param {*} color 颜色
       */
      constructor(ctx, x, y, size, color) {
        super(ctx, x, y, size, color);
        this.targetX = window.innerWidth / 2;
        this.targetY = window.innerHeight / 2;
        const langx = 550;
        const langy = 550;
        if (
          this.x > this.targetX - langx &&
          this.x < this.targetX + langx &&
          this.y > this.targetY - langy &&
          this.y < this.targetY + langy
        ) {
          this.x = this.x >= this.targetX ? this.x + langx : this.x - langx;
          this.y = this.y >= this.targetY ? this.y + langy : this.y - langy;
        }
        this.speed = Math.random() * 0.01 + 0.005;
      }
      move() {
        this.rotate += this.speed * 100;
        this.size -= this.size * this.speed;
        this.x += (this.targetX - this.x) * 0.002;
        this.y += (this.targetY - this.y) * 0.002;
        if (this.size >= 0.01) {
          this.init();
        } else {
          this.destory(); // size小于0.01销毁
        }
      }
    }

    class starMouse extends Arc {
      /**
       * @desc 鼠标拖尾特效
       * @param {*} ctx canvas上下文
       * @param {*} x x坐标位置
       * @param {*} y y坐标位置
       * @param {*} size 大小
       * @param {*} color 颜色
       */
      constructor(ctx, x, y, size, color) {
        super(ctx, x, y, size, color);
        this.speedx = (Math.random() - 0.5) * 0.01;
        this.speedy = (Math.random() - 0.5) * 0.01;
        this.opacity = 1;
        this.color = randomColor()
      }
      move() {
        this.size -= this.size * 0.05;
        this.x += this.x * this.speedx;
        this.y += this.y * this.speedy;
        this.rotate += this.speedx * 500;
        this.opacity -= 0.01;
        if (this.opacity >= 0) {
          this.init();
        } else {
          this.destory();
        }
      }
    }

    // 飘花特效
    function createCirlce() {
      setInterval(() => {
        // 数量限制为100
        if (circleArr.length >= 200) return
        let circle = new Star(ctx,randomPos(1500),randomPos(1500),randomPos(80),randomColor());
        circleArr.push(circle);
      }, 200);
    }

    // 拖尾特效
    function createParticle(e) {
      let mstar = new starMouse(ctx, e.clientX, e.clientY, 20, randomColor());
      ctx.mstars.push(mstar);
    }

    function run() {
      let array = [];
      if (playing) {
        array = new GetAudio().createAudio();
      }
      new CirLine().move(array);
      circleArr.forEach((circle, index) => {
        circle.move();
        circle.destory = () => {
          circleArr.splice(index, 1);
          circle = null;
        };
      });

      ctx.mstars.forEach((mstar, index) => {
        mstar.move();
        mstar.destory = () => {
          ctx.mstars.splice(index, 1);
          mstar = null;
        };
      });
    }

    function animation() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      run();
      reqId = requestAnimationFrame(animation);
    }
    // 随机颜色
    function randomColor(opacity = 1) {
      return `rgba(${Math.random() * 255},${Math.random() * 255},${
        Math.random() * 255
      },${opacity})`;
    }
    // 随机位置
    function randomPos(num) {
      return Math.random() * num;
    }

    document.onclick = function () {
      // console.log(ctx.mstars);
      // draw()
    };

    function drawC(ctx, positionX, positionY, r, color) {
      ctx.save();
      ctx.beginPath(0, 0);
      ctx.arc(
        positionX,
        positionY,
        r,
        (360 / 180) * Math.PI,
        (0 / 180) * Math.PI,
        true
      );
      ctx.closePath();
      ctx.fill();
      ctx.restore();
    }

    function drawHeart(ctx, positionX = 0, positionY = 0, r, rotate, color) {
      ctx.save();
      ctx.translate(positionX + r, positionY + r);
      ctx.rotate(((rotate + 225) * Math.PI) / 180);
      ctx.fillStyle = color;
      drawC(ctx, r, r * 2, r);
      drawC(ctx, r * 2, r, r);
      ctx.beginPath(0, 0);
      ctx.rect(0, 0, r * 2, r * 2);
      ctx.closePath();
      ctx.fill();
      ctx.restore();
    }
    /**
     *
     * @param {*} deg 线条角度
     * @param {*} l 长度
     * @param {*} w 线宽
     * @param {*} r 半径
     * @param {*} rotate 整体旋转角度
     * @param {*} scalenum 缩放倍数
     * @param {*} color 颜色
     */
    function scale(deg, l, w, r = 200, rotate, scalenum = 1, color = "black") {
      ctx.save();
      ctx.translate(canvas.width / 2, canvas.height / 2);
      ctx.rotate((rotate * Math.PI) / 180);
      deg -= 90;
      let x = ((2 * Math.PI) / 360) * deg;
      ctx.beginPath();
      ctx.strokeStyle = color;
      ctx.lineWidth = w;
      ctx.shadowOffsetX = 2;
      ctx.shadowOffsetY = 2;
      let t = 0;
      ctx.scale(scalenum, scalenum);
      ctx.moveTo(t + (r - l) * Math.cos(x), t + (r - l) * Math.sin(x));
      ctx.lineTo(t + (r + l) * Math.cos(x), t + (r + l) * Math.sin(x));
      ctx.closePath();
      ctx.stroke();
      ctx.restore();
    }
    // 表盘数字
    function addText(deg, rotate, scalenum) {
      let text = "12";
      if (deg !== 0) {
        text = deg / 30;
      }
      deg -= 90;
      ctx.save();
      ctx.translate(canvas.width / 2, canvas.height / 2);
      ctx.rotate((rotate * Math.PI) / 180);
      ctx.font = "30px 微软雅黑";
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      ctx.shadowBlur = 1;
      ctx.shadowColor = "balck";
      ctx.shadowOffsetX = 3;
      ctx.shadowOffsetY = 3;
      ctx.scale(scalenum, scalenum);
      ctx.fillText(
        text,
        170 * Math.cos(((2 * Math.PI) / 360) * deg),
        170 * Math.sin(((2 * Math.PI) / 360) * deg)
      );
      ctx.restore();
    }

    function drawCirLine(rotate, scalenum,array) {
      for (let i = 0; i < 360; i++) {
        if (i % 6 === 0) {
          if (i % 90 === 0) {
            addText(i, -rotate, scalenum);
            scale(i, 10, 4, undefined, -rotate, scalenum,'#fff');
          } else if (i % 30 === 0) {
            addText(i, -rotate, scalenum);
            scale(i, 10, 2, undefined, -rotate, scalenum,'#fff');
          } else {
            scale(i, 5, 1, undefined, -rotate, scalenum,'#fff');
          }
        }
        // scale(i, 5, 0.5, 200, -rotate, scalenum,`rgb(0,200,${getcolor(i,rotate)})`);
        // scale(i, 5, 0.5, 170, rotate, scalenum,`rgb(10,100,${getcolor(i,rotate)})`);
        scale(i, getLine(array[i+100],10), 0.5, 230, rotate, scalenum,`rgb(200,0,${getcolor(i,rotate)})`);
      }
    }

    function getcolor(i,deg){
      if (i + deg < 255) {
        return i + deg
      } else {
        return (255- (i + deg)%255)
      }
    }
    function getLine(l,target){
      if(l === 0){
        return target - target + 2
      } else if ( l > target ){
        return target + (l-target)/target * 5 + 2
      } else if ( l < target ){
        return target + (l-target)/(l+target) * target + 2
      }
    }

    window.onresize = () => {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    };

    return () => {
      window.onresize = null
      // animation()
    };
  }, []);

  return (
    <div className="canvaspage">
      <canvas ref={canvas} id="canvas"></canvas>
      <div className="progress">
        <div id="total" data-value="00:00 / 00:00" className="total">
          <div className="current"></div>
        </div>
      </div>
      <div className="container">
        <div id="btn1" className="btn">
          <a>播 放</a>
        </div>
        <div id="btn2" className="btn">
          <a>播 放</a>
        </div>
        <div id="btn3" className="btn">
          <a>播 放</a>
        </div>
      </div>
      <footer>
        <a className="beian" src="https://beian.miit.gov.cn/" target="_blank">
          豫ICP备2023008742号
        </a>
      </footer>
    </div>
  );
}

export default Canvas;
